package cn.virens.common.easyexcel.dict;

import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import cn.idev.excel.write.handler.CellWriteHandler;
import cn.idev.excel.write.handler.context.CellWriteHandlerContext;
import cn.virens.common.util.exception.APIException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ObjUtil;

import java.util.Arrays;

public abstract class AbstractExcelDictConverter<T> implements Converter<T>, CellWriteHandler {
    private String defLabel = StrUtil.EMPTY;

    /**
     * 创建数据验证列
     */
    protected void createValidation(CellWriteHandlerContext context, Cell cell, ExcelDict excelDict) throws APIException {
        CellRangeAddressList addressList = new CellRangeAddressList(-1, -1, cell.getColumnIndex(), cell.getColumnIndex());

        DataValidationHelper helper = context.getWriteSheetHolder().getSheet().getDataValidationHelper();

        DataValidationConstraint constraint = helper.createExplicitListConstraint(excelDict.getKeyArray());
        DataValidation dataValidation = helper.createValidation(constraint, addressList);
        context.getWriteSheetHolder().getSheet().addValidationData(dataValidation);
    }

    @Override
    public T convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return cellData != null ? ((T) getExcelDict().get(cellData.getStringValue())) : null;
    }

    @Override
    public WriteCellData<?> convertToExcelData(T value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new WriteCellData<>(str(getExcelDict().getKey(value)));
    }

    protected void afterCellCreate0(CellWriteHandlerContext context, ExcelDict excelDict) {
        if (excelDict != null && excelDict.includeHeadName(getHeadName(context))) {
            this.createValidation(context, context.getCell(), excelDict);
        }
    }

    /**
     * 获取列表表头
     */
    protected String getHeadName(CellWriteHandlerContext context) throws APIException {
        return CollUtil.getLast(context.getHeadData().getHeadNameList());
    }

    @Override
    public void afterCellCreate(CellWriteHandlerContext context) throws APIException {
        this.afterCellCreate0(context, getExcelDict());
    }

    /**
     * 生成对应的字典构建器
     */
    protected static <T> ExcelDictBuilder<T> builder0(String... hname) {
        return new ExcelDictBuilder<>(Arrays.asList(hname));
    }

    /**
     * 获取当前对象对应的字典
     */
    protected ExcelDict getExcelDict() throws APIException {
        return ExcelDictStack.getDict(getClass());
    }

    /**
     * 防止空字符串
     */
    protected String str(String str) throws APIException {
        if (str == null || str.isEmpty()) {
            return defLabel;
        }

        return str;
    }

    /**
     * 设置默认字符串显示内容
     */
    public void setDefLabel(String defLabel) {
        this.defLabel = defLabel;
    }

    @Override
    public Class<?> supportJavaTypeKey() throws APIException {
        return ObjUtil.getTypeArgument(this);
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }
}
